package com.gitee.kenewstar.migration.function;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.gitee.kenewstar.migration.constants.Const;
import com.gitee.kenewstar.migration.constants.FunctionCode;
import com.gitee.kenewstar.migration.core.AbstractSyncFunction;
import com.gitee.kenewstar.migration.core.ContextParam;
import com.gitee.kenewstar.migration.entity.CommonResult;
import com.gitee.kenewstar.migration.entity.Lov;
import com.gitee.kenewstar.migration.entity.LovTl;
import com.gitee.kenewstar.migration.entity.LovValue;
import com.gitee.kenewstar.migration.entity.LovValueTl;
import com.gitee.kenewstar.migration.service.LovService;
import lombok.Builder;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author kenewstar
 */
@Slf4j
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class LovFunction extends AbstractSyncFunction<Lov> {

    private final LovService lovService;

    @Override
    protected Class<Lov> parameterType() {
        return Lov.class;
    }

    @Override
    public FunctionCode functionCode() {
        return FunctionCode.LOV;
    }

    @Override
    @DS(Const.UAT)
    @Transactional(rollbackFor = Exception.class)
    public void singleExecute(ContextParam contextParam) {
        Lov lov = contextParam.lovContext.lov;
        Map<Long, List<LovTl>> lovTlListMap = contextParam.lovContext.lovTlListMap;
        Map<Long, List<LovValue>> lovValueListMap = contextParam.lovContext.lovValueListMap;
        Map<Long, List<LovValueTl>> lovValueTlsMap = contextParam.lovContext.lovValueTlsMap;

        Long srcLovId = lov.getLovId();
        List<LovTl> list = lovTlListMap.get(srcLovId);
        lov.setLovId(null);
        lovService.uatInsertLov(ListUtil.toList(lov));
        list.forEach(v -> v.setLovId(lov.getLovId()));
        lovService.uatInsertLovTl(list);

        // 值集列表
        List<LovValue> lovValues = lovValueListMap.get(srcLovId);
        if (CollUtil.isNotEmpty(lovValues)) {
            lovValues.forEach(v -> v.setLovId(lov.getLovId()));
            lovValues.forEach(v -> v.setSrcLovValueId(v.getLovValueId()));
            lovValues.forEach(v -> v.setLovValueId(null));
            lovService.uatInsertLovValue(lovValues);
        }
        if (CollUtil.isEmpty(lovValues)) {
            return;
        }
        List<LovValueTl> lovValueTlList = new ArrayList<>(10);
        // 多语言列表
        for (LovValue lovValue : lovValues) {
            List<LovValueTl> valueTls = lovValueTlsMap.get(lovValue.getSrcLovValueId());
            valueTls.forEach(v -> v.setLovValueId(lovValue.getLovValueId()));
            lovValueTlList.addAll(valueTls);
        }
        this.lovService.uatInsertLovValueTl(lovValueTlList);
    }

    @Override
    public List<CommonResult> execute(ContextParam contextParam, List<Lov> list) {
        // 查询所有值集
        final List<Lov> lovList = this.lovService.devSelectLovList(list);
        if (CollUtil.isEmpty(lovList)) {
            return Collections.emptyList();
        }

        // 值集多语言
        QueryWrapper<LovTl> wrapper = new QueryWrapper<>();
        wrapper.in("lov_id", lovList.stream().map(Lov::getLovId).collect(Collectors.toList()));
        final List<LovTl> lovTls1 = this.lovService.devSelectTl(wrapper);
        final Map<Long, List<LovTl>> lovTlListMap = lovTls1.stream().collect(Collectors.groupingBy(LovTl::getLovId));

        QueryWrapper<LovValue> valueQueryWrapper = new QueryWrapper<>();
        valueQueryWrapper.in("lov_id", lovList.stream().map(Lov::getLovId).collect(Collectors.toList()));
        final List<LovValue> lovValueList = this.lovService.devSelectLovValue(valueQueryWrapper);
        final Map<Long, List<LovValue>> lovValueListMap = lovValueList.stream().collect(Collectors.groupingBy(LovValue::getLovId));

        QueryWrapper<LovValueTl> lovValueTlQueryWrapper = new QueryWrapper<>();
        Map<Long, List<LovValueTl>> lovValueTlsMap;
        final List<Long> lovValueIds = lovValueList.stream().map(LovValue::getLovValueId).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(lovValueIds)) {
            lovValueTlQueryWrapper.in("lov_value_id", lovValueIds);
            final List<LovValueTl> lovValueTls = this.lovService.devSelectLovValueTl(lovValueTlQueryWrapper);
            lovValueTlsMap = lovValueTls.stream().collect(Collectors.groupingBy(LovValueTl::getLovValueId));
        } else {
            lovValueTlsMap = new HashMap<>(0);
        }

        contextParam.lovContext = Context.builder().build();
        contextParam.lovContext.lovTlListMap = lovTlListMap;
        contextParam.lovContext.lovValueListMap = lovValueListMap;
        contextParam.lovContext.lovValueTlsMap = lovValueTlsMap;

        List<CommonResult> results = new ArrayList<>(lovList.size());
        lovList.forEach(v -> {
            try {
                contextParam.lovContext.lov = v;
                this.self().singleExecute(contextParam);
                results.add(CommonResult.create(true).setLovCode(v.getLovCode()));
            } catch (Exception e) {
                results.add(CommonResult.create(false).setLovCode(v.getLovCode()).setErrorMsg(e.getMessage()));
                e.printStackTrace();
            }
        });
        return results;
    }

    @Builder
    @SuppressWarnings("all")
    public static class Context {
        public Lov lov;
        public Map<Long, List<LovTl>> lovTlListMap;
        public Map<Long, List<LovValue>> lovValueListMap;
        public Map<Long, List<LovValueTl>> lovValueTlsMap;

    }


}
